package org.smart4j.framework;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smart4j.framework.bean.Data;
import org.smart4j.framework.bean.Handler;
import org.smart4j.framework.bean.Param;
import org.smart4j.framework.bean.View;
import org.smart4j.framework.helper.*;
import org.smart4j.framework.util.JsonUtil;
import org.smart4j.framework.util.ReflectionUtil;
import org.smart4j.framework.util.RequestHelper;
import org.smart4j.framework.util.StringUtil;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 请求转发器
 *
 * Created by chinalin on 2017/3/16.
 */
@WebServlet(urlPatterns = "/*" , loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet{

    private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class) ;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        LOGGER.info("Dis:init");
        //初始化相关 Helper 类
        HelperLoader.init();
        //获取 ServletContext 对象(用于注册 Servlet)
        ServletContext servletContext = servletConfig.getServletContext() ;
        //注册处理 JSP 的Servlet
        ServletRegistration jspServlet = servletContext.getServletRegistration("jsp") ;
        jspServlet.addMapping(ConfigHelper.getAppJspPath() + "*") ;
        //注册处理静态资源的默认 Servlet
        ServletRegistration defaultServlet = servletContext.getServletRegistration("default") ;
        defaultServlet.addMapping(ConfigHelper.getAppAssetPath() + "*") ;

        UploadHelper.init(servletContext);  //文件上传助手
    }

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        LOGGER.info("Dis:service");
        ServletHelper.init(request,response);   //初始化线程安全的ServletHelper类
        try {
            //获取请求方法和请求路径
            String requestMethod = request.getMethod().toLowerCase() ;
            String requestPath = request.getPathInfo() ;
            if (requestPath.equals("/favicon.ico")){  //网站图标
                return;
            }

            //获取 Action 处理器
            Handler handler = ControllerHelper.getHandler(requestMethod,requestPath) ;
            if (handler != null){
                //获取 Controller 类以其 Bean 实例
                Class<?> controllerClass = handler.getControllerClass() ;
                Object controllerBean = BeanHelper.getBean(controllerClass) ;

                //创建请求参数对象
                Param param ;
                if (UploadHelper.isMultipart(request)){
                    param = UploadHelper.createParam(request) ;
                }else {
                    param = RequestHelper.createParam(request) ;
                }

                Object result ;
                //调用 Action 方法
                Method actionMethod = handler.getActionMethod() ;
                /**
                 * 优化action方法，区别有参数和无参数的方法
                 */
                if (param.isEmpty()){
                    result = ReflectionUtil.invokeMethod(controllerBean, actionMethod) ;
                }else {
                    result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param) ;
                }

                //处理 Action 方法返回值
                if (result instanceof View){
                    //返回 JSP 页面
                    handleViewResult((View)result,request,response);
                }else if (result instanceof Data){
                    //返回 JSON 数据
                    handleDataResult((Data) result,response);
                }
            }
        }finally {
            ServletHelper.destroy();
        }
    }

    private void handleViewResult(View view,HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
        String path = view.getPath() ;
        if (StringUtil.isNotEmpty(path)){
            if (path.startsWith("/")){
                System.out.println("跳转的路径" + request.getContextPath() + path);
                response.sendRedirect(request.getContextPath() + path);
            } else {
                Map<String, Object> model = view.getModel() ;
                for (Map.Entry<String, Object> entry : model.entrySet()) {
                    request.setAttribute(entry.getKey(), entry.getValue());
                }
                request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request,response);
            }
        }
    }

    private void handleDataResult(Data data,HttpServletResponse response)throws IOException{
        Object model = data.getModel() ;
        if (model != null){
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            PrintWriter writer = response.getWriter() ;
            String json = JsonUtil.toJson(model) ;
            writer.write(json);
            writer.flush();
            writer.close();
        }
    }
}
